﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Runtime.Serialization;
using G.Controls;
using Microsoft.Phone.Controls;
using System.Text.RegularExpressions;

namespace G.Net.Oauth
{
    public class Oauth2Valid
    {
        /// <summary>
        /// 刷新AccessToken
        /// </summary>
        /// <returns></returns>
        public static void RefreshToken(string appName, Action<OAuth2AccessToken> callBack)
        {
            OAuth2AccessToken.Load("OAuth2AccessToken" + appName);
            if (OAuth2AccessToken.CurrentToken == null)
            {
                throw new Exception("无法获取OAuth2AccessToken，请重新登陆");
            }
            string refreshTokenUrl = string.Format("{0}?client_id={1}&client_secret={2}&grant_type=refresh_token&refresh_token={3}&scope=read,write", Oauth2Config.Token_Authorize_Url, Oauth2Config.ClientID, Oauth2Config.ClientSecret, OAuth2AccessToken.CurrentToken.RefreshToken);
            HttpPost post = new HttpPost(refreshTokenUrl);
            post.Request((stats, msg) =>
            {
                if (stats == WebExceptionStatus.Success)
                {
                    OAuth2AccessToken token = G.Utils.SerializerHelp.JsonDeserialize<OAuth2AccessToken>(msg);
                    token.Save("OAuth2AccessToken" + appName, msg);
                }
                else
                    throw new Exception("获取token失败");
            });
        }


        private static void GetCode(Action<string> callBack)
        {
            ChildWindow c = new ChildWindow();
            WebBrowser web = new WebBrowser();
            c.Content = web;
            string authorize_url = string.Format("{0}?client_id={1}&response_type={2}&redirect_uri={3}&scope=read,write", Oauth2Config.Request_Authorize_Url, Oauth2Config.ClientID, Oauth2Config.Authorize_ResponseType, HttpUtility.UrlEncode(Oauth2Config.RedirectUri));
            web.Navigate(new Uri(authorize_url));
            c.IsOpen = true; ;
            web.LoadCompleted += (s, e) =>
            {
                if (e.Uri.OriginalString.StartsWith(Oauth2Config.RedirectUri))
                {
                    string code = e.Uri.Query;
                    string pa = "code=(.+?)$";
                    var match = Regex.Match(code, pa, RegexOptions.IgnoreCase);
                    if (!match.Success)
                        throw new Exception("检索code失败！");
                    code = match.Groups[1].Value;
                    c.IsOpen = false;
                    callBack(code);
                }
            };
        }

        public static void Valid(string appName, string code, Action<OAuth2AccessToken> callBack)
        {
            HttpPost post = new HttpPost(string.Format("{0}?client_id={1}&client_secret={2}&grant_type={3}&redirect_uri={4}&code={5}", Oauth2Config.Token_Authorize_Url, Oauth2Config.ClientID, Oauth2Config.ClientSecret, "authorization_code", Oauth2Config.RedirectUri, code));
            post.Request((staus, str) =>
            {
                if (staus == WebExceptionStatus.Success)
                {
                    OAuth2AccessToken token = Utils.SerializerHelp.JsonDeserialize<OAuth2AccessToken>(str);
                    token.Save("OAuth2AccessToken" + appName, str);
                    callBack(token);
                }
                else
                    throw new Exception("获取token失败");
            });
        }

        /// <summary>
        /// 验证oauth2.0权限，获取AccessToken
        /// </summary>
        /// <returns></returns>
        public static void Valid(string appName, Action<OAuth2AccessToken> callBack)
        {
            var t = OAuth2AccessToken.Load("OAuth2AccessToken" + appName);
            if (t != null)
            {
                callBack(t);
                return;
            }
            GetCode((c) =>
            {
                Valid(appName, c, callBack);
            });
        }

        public static bool IsLogin(string appName)
        {
            var t = OAuth2AccessToken.Load("OAuth2AccessToken" + appName);
            if (t == null)
                return false;
            return true;
        }

        public static void Logout(string appName)
        {
            OAuth2AccessToken.Clear("OAuth2AccessToken" + appName);
        }
    }

    [DataContract]
    public class OAuth2AccessToken
    {
        internal static OAuth2AccessToken Load(string key)
        {
            var settings = System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings;
            if (settings.Contains(key))
            {
                var token = Utils.SerializerHelp.JsonDeserialize<OAuth2AccessToken>(settings[key] as string);
                CurrentToken = token;
                return token;
            }
            return null;
        }

        internal static void Clear(string key)
        {
            var settings = System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings;
            if (settings.Contains(key))
            {
                settings.Remove(key);
                settings.Save();
            }
        }

        public static OAuth2AccessToken CurrentToken { get; internal set; }
        public OAuth2AccessToken()
        {
            CurrentToken = this;
        }

        [DataMember(Name = "access_token")]
        public string AccessToken { get; set; }

        [DataMember(Name = "expires_in")]
        public string ExpiresIn { get; set; }

        [DataMember(Name = "refresh_token")]
        public string RefreshToken { get; set; }

        [DataMember(Name = "token_type")]
        public string TokenType { get; set; }

        [DataMember(Name = "uid")]
        public string Uid { get; set; }

        [DataMember(Name = "scope")]
        public string Scope { get; set; }

        internal void Save(string key, string jsonStr)
        {
            var settings = System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings;
            settings[key] = jsonStr;
            settings.Save();
            CurrentToken = this;
        }
    }
}
